package main

import (
	"fmt"
	"io"
	"io/fs"
	"io/ioutil"
	"os"
	"strings"
	"bytes"
)

func main()  {
	//ioMain()
	//fsMain()
	ioutilMain()

}

func ioMain()  {
	// 将 s 写入 到 w 中，并返回写入数据字节数
	ioWriteString,_ := io.WriteString(os.Stdout,"aaabbbccc")
	fmt.Println(ioWriteString)

	// 从 r 中读取至少 min 字节到 buf 中，
	buf := make([]byte, 10)
	ioReadAtLeast,_ := io.ReadAtLeast(strings.NewReader("aaabbbccc"),buf,6)
	fmt.Println(ioReadAtLeast)
	fmt.Println(string(buf))

	// 从 r 中读取 len(buf) 字节到buf中
	ioReadFull,_ := io.ReadFull(strings.NewReader("aaabbbccc"),make([]byte, 8))
	fmt.Println(ioReadFull)

	// 从 src 读取 n 字节到 dst 中，返回复制的字节数
	ioCopyN,_ := io.CopyN(os.Stdout,strings.NewReader("aaabbbccc"),6)
	fmt.Println(ioCopyN)

	// 从 src 读取字节到 dst 中，返回复制的字节数
	ioCopy,_ := io.Copy(os.Stdout,strings.NewReader("aaabbbccc"))
	fmt.Println(ioCopy)

	// 从 src 中读取数据缓冲到 buf ，最后写入到 dst，buf 不是临时缓冲
	ioCopyBuff,_ := io.CopyBuffer(os.Stdout,strings.NewReader("aaabbbccc"),make([]byte, 8))
	fmt.Println(ioCopyBuff)

	// 从 r 中读取 n 字节，并返回一个 reader 接口
	ioLimitReader := io.LimitReader(strings.NewReader("aaabbbccc"),8)
	fmt.Println(ioLimitReader.Read([]byte("aaabbb")))


	// 从 r 的偏移量 off 开始读取 n 字节的数据，并返回一个读接口
	ioNewSectionReader := io.NewSectionReader(strings.NewReader("aaabbbccc"),1,6)

	// 从接口中读取数据，并返回读取的字节数
	fmt.Println(ioNewSectionReader.Read([]byte("aabb")))

	// 从读接口数据的 whence 开始，偏移 offset 进行数据读取并填充读接口
	fmt.Println(ioNewSectionReader.Seek(1,2))

	// 从读接口的偏移 off 开始读数据，填充 p
	fmt.Println(ioNewSectionReader.ReadAt([]byte("aabb"),2))

	// 返回读接口数据大小
	fmt.Println(ioNewSectionReader.Size())


	// 从 r 读取的内容写入 w 并返回一个读的接口
	ioTeeReader := io.TeeReader(strings.NewReader("aaabbbccc"),os.Stdout)

	// 返回读取的数量
	ioTeeReaderInt,_ := ioTeeReader.Read([]byte("ddee"))
	fmt.Println(ioTeeReaderInt)


	// 从 r 读取数据并返回读取的数据
	ioReadAll,_ := io.ReadAll(strings.NewReader("aaabbbccc"))
	fmt.Println(string(ioReadAll))


	// 多个读接口返回一个读接口
	ioMultireader := io.MultiReader(strings.NewReader("aaabbbccc"),strings.NewReader("dddeeefff"))
	io.Copy(os.Stdout, ioMultireader)

	// 多个写的接口，写入一个接口
	var buf1, buf2 bytes.Buffer
	w := io.MultiWriter(&buf1, &buf2)
	io.Copy(w, strings.NewReader("aaabbbcccddd"))
	fmt.Print(buf1.String())
	fmt.Print(buf2.String())


	// 创建一个管道，返回管道阅读器和管道写入器
	iopipereader,iopipewrite := io.Pipe()
	go func() {
		fmt.Fprint(iopipewrite, "some io.Reader stream to be read\n")
		iopipewrite.Close()
	}()
	if _, err := io.Copy(os.Stdout, iopipereader); err != nil {
		fmt.Println(err)
	}

}

func fsMain()  {
	// 文件路径名是否有效
	fsValidPath := fs.ValidPath("ngfvhgf")
	fmt.Println(fsValidPath)

	// 返回文件的字符串格式的权限,0777
	fmt.Println(fs.ModePerm.String())

	// 是否是目录
	fmt.Println(fs.ModePerm.IsDir())

	// 是否是常规文件
	fmt.Println(fs.ModePerm.IsRegular())

	// 返回权限位
	fmt.Println(fs.ModePerm.Perm())

	// 返回类型位
	fmt.Println(fs.ModePerm.Type())

	fs.FS(os.DirFS("osMain.go")).Open("osMain.go")


	root := "G:\\goData\\go源码"
	fileSystem := os.DirFS(root)

	// 返回与模式匹配的所有文件的名称，如果没有匹配的文件，则返回nil
	fsGlob,fsGlobErr := fs.Glob(fileSystem,"G:\\goData\\go源码")
	fmt.Println(fsGlob,fsGlobErr)

	// 读取目，返回按文件名排序的目录项列表。DirEntry interface
	fsReadDir,fsReadDirErr := fs.ReadDir(fileSystem,".")
	fmt.Println(fsReadDir,fsReadDirErr)
	// 文件或子目录名称
	fmt.Println(fsReadDir[0].Name())
	// 是否是目录
	fmt.Println(fsReadDir[0].IsDir())
	// 文件类型
	fmt.Println(fsReadDir[0].Type())
	// 文件信息
	fmt.Println(fsReadDir[0].Info())

	// 从文件系统fs读取命名文件并返回其内容
	fsReadFile,fsReadFileErr := fs.ReadFile(fileSystem,"test.txt")
	fmt.Println(string(fsReadFile),fsReadFileErr)

	// 返回一个文件信息，描述文件系统中的命名文件,FileInfo interface
	fsStat,fsStatErr := fs.Stat(fileSystem,"test.txt")
	fmt.Println(fsStat,fsStatErr)
	// 文件名称
	fmt.Println(fsStat.Name())
	// 文件模式位
	fmt.Println(fsStat.Mode())
	// 文件修改时间
	fmt.Println(fsStat.ModTime())
	// 是否是目录
	fmt.Println(fsStat.IsDir())
	// 基础数据源
	fmt.Println(fsStat.Sys())

	// FileInfo 转 DirEntry
	fsFileInfoToDirEntry := fs.FileInfoToDirEntry(fsStat)
	fmt.Println(fsFileInfoToDirEntry)
	// 文件信息
	fmt.Println(fsFileInfoToDirEntry.Info())

	// 返回一个FS，该FS对应于以fsys的dir为根的子目录
	fsFs,fsFsErr := fs.Sub(fileSystem,".")
	fmt.Println(fs.ReadFile(fsFs,"test.txt"))
	fmt.Println(fsFsErr)

	// 遍历根目录下的文件树，为树中的每个文件或 目录（包括根目录）调用fn。
	fs.WalkDir(fileSystem, ".", func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			fmt.Println(err)
		}
		fmt.Println(path)
		return nil
	})

}

func ioutilMain()  {
	// 从 r 读取，并返回读取的内容，从 io.ReadAll 读
	ioutilReadAll,_ := ioutil.ReadAll(strings.NewReader("aaabbbccc"))
	fmt.Println(string(ioutilReadAll))

	// 读取文件，并返回内容，从 os.ReadFile 读
	ioutilReadFile,_ := ioutil.ReadFile("test.txt")
	fmt.Println(string(ioutilReadFile))

	// 将数据写入文件，若文件不存在，则创建文件，存在，则会清空文件，从 os.WriteFile 写
	ioutil.WriteFile("test.txt",[]byte("zzzcccxxx"),0777)

	// 读取目录，并返回一个按文件名排序的 fs 列表
	ioutilReadDir,_ := ioutil.ReadDir(".")
	fmt.Println(ioutilReadDir[3].Name())

	// r 无操作则关闭
	ioutil.NopCloser(strings.NewReader("aaabbbccc"))


	// 在目录中创建一个新的临时文件，从 os.CreateTemp 创建
	println(os.TempDir())
	ioutilTempFile,_ := ioutil.TempFile(".","*-logs")
	fmt.Println(ioutilTempFile.Name())

	// 在目录中创建一个新的临时目录，从 os.MkdirTemp 创建
	ioutilTempDir,_ := ioutil.TempDir(".","*-logss")
	fmt.Println(ioutilTempDir)

}